package com.farm.wcp.controller;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.lucene.queryparser.classic.ParseException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.alibaba.fastjson.JSON;
import com.farm.core.page.ViewMode;
import com.farm.iproject.domain.Appmodel;
import com.farm.iproject.domain.Dictype;
import com.farm.iproject.domain.Field;
import com.farm.iproject.domain.Project;
import com.farm.iproject.service.AppmodelServiceInter;
import com.farm.iproject.service.DictypeServiceInter;
import com.farm.iproject.service.FieldServiceInter;
import com.farm.iproject.service.PopgroupServiceInter;
import com.farm.iproject.service.ProjectServiceInter;
import com.farm.iproject.service.SearchrecordServiceInter;
import com.farm.iproject.service.VirtualfieldServiceInter;
import com.farm.iproject.service.VisitrecordServiceInter;
import com.farm.sfile.WdapFileServiceInter;
import com.farm.sfile.enums.FileModel;
import com.farm.sfile.service.FileBaseServiceInter;
import com.farm.wcp.util.BootstrapTreeViews;
import com.farm.web.WebUtils;
import com.farm.wsch.index.WschSearchServerInter;
import com.farm.wsch.index.pojo.IndexResult;
import com.farm.wsch.index.pojo.ResultDicNum;
import com.farm.wsch.index.pojo.RuleInfo;
import com.farm.wuc.events.WucEventModle;
import com.farm.wuc.events.WucEventRole;
import com.farm.wuc.events.WucService;

import om.wuc.client.events.WucEventRecorder;
import om.wuc.client.events.domain.WucEventInfo;
import om.wuc.client.events.domain.WucEventUsers;

/**
 * 文件
 * 
 * @author autoCode
 * 
 */
@RequestMapping("/search")
@Controller
public class SearchWebController extends WebUtils {
	private static final Logger log = Logger.getLogger(SearchWebController.class);
	@Resource
	private WdapFileServiceInter wdapFileServiceImpl;
	@Resource
	private ProjectServiceInter projectServiceImpl;
	@Resource
	private FieldServiceInter fieldServiceImpl;
	@Resource
	private AppmodelServiceInter appModelServiceImpl;
	@Resource
	private VirtualfieldServiceInter virtualFieldServiceImpl;
	@Resource
	private DictypeServiceInter dicTypeServiceImpl;
	@Resource
	private PopgroupServiceInter popGroupServiceImpl;
	@Resource
	private SearchrecordServiceInter searchRecordServiceImpl;
	@Resource
	private VisitrecordServiceInter visitRecordServiceImpl;
	@Resource
	private FileBaseServiceInter fileBaseServiceImpl;

	/***
	 * 首页
	 * 
	 * @param session
	 * @return
	 */
	@RequestMapping("/Pubhome")
	public ModelAndView index(String projectid, HttpServletRequest request, HttpSession session) {
		ViewMode view = ViewMode.getInstance();
		try {
			List<Map<String, Object>> hotdocs = visitRecordServiceImpl.getHotDoc(projectid, 10,
					getCurrentUser(session) == null ? null : getCurrentUser(session).getId());
			if (StringUtils.isBlank(projectid)) {
				projectid = projectServiceImpl.getProjects().get(0).getId();
			}
			initSearchPageParas(view, projectid);

			Project project = projectServiceImpl.getProjectEntity(projectid);

			if (StringUtils.isNotBlank(project.getMinimgid())) {
				view.putAttr("minlogourl", fileBaseServiceImpl.getDownloadUrl(project.getMinimgid(), FileModel.IMG));
			}
			if (StringUtils.isNotBlank(project.getMaximgid())) {
				view.putAttr("maxlogourl", fileBaseServiceImpl.getDownloadUrl(project.getMaximgid(), FileModel.IMG));
			}

			return view.putAttr("hotdocs", hotdocs).returnModelAndView("web-simple/search/index");
		} catch (Exception e) {
			return view.setError(e.getMessage(), e).returnModelAndView("web-simple/simple-500");
		}
	}

	/***
	 * 执行检索
	 * 
	 * @param projectid  项目id
	 * @param appkeyid   业务key
	 * @param fieldkeyid 字段key（检索字段）
	 * @param word       关键字
	 * @param page       当前页
	 * @param dicrule    字典条件
	 * @param request
	 * @param session
	 * @return
	 */
	@RequestMapping("/Pubdo")
	public ModelAndView dosearch(String projectid, String pkey, String appkeyid, String fieldkeyid, String word,
			Integer page, String dicrule, String resultid, String sortkey, String sorttype, String sorttitle,
			Boolean isSmart, HttpServletRequest request, HttpSession session) {
		ViewMode view = ViewMode.getInstance();
		if (StringUtils.isNotBlank(pkey)) {
			Project project = projectServiceImpl.getProjectByKey(pkey);
			if (project != null) {
				projectid = project.getId();
			}
		}
		if (StringUtils.isBlank(projectid) || StringUtils.isBlank(word)) {
			return view.returnRedirectUrl("/search/Pubhome.do");
		}
		try {
			word = URLDecoder.decode(URLDecoder.decode(word, "utf-8"), "utf-8");
		} catch (UnsupportedEncodingException e1) {
			e1.printStackTrace();
		}
		try {
			if (StringUtils.isBlank(appkeyid)) {
				appkeyid = "ALL";
			}
			if (StringUtils.isBlank(fieldkeyid)) {
				fieldkeyid = "ALL";
			}
			// 初始化页面参数
			initSearchPageParas(view, projectid);
			if (page == null) {
				page = 1;
			}

			List<ResultDicNum> dics = dicTypeServiceImpl.getResultDicNums(projectid, appkeyid);
			Set<String> popkeys = popGroupServiceImpl.getUserSearchKeys(projectid,
					getCurrentUser(session) == null ? null : getCurrentUser(session).getId());
			if (isSmart == null) {
				isSmart = false;
			}
			IndexResult result = runDoSearch(projectid, appkeyid, fieldkeyid, word, page, dicrule, resultid, sortkey,
					sorttype, dics, popkeys, isSmart);
			List<Dictype> dicunits = initStatDics(dics, projectid);
			Map<String, Appmodel> appModels = appModelServiceImpl.getAppmodelMap(projectid);
			for (Map<String, Object> node : result.getList()) {
				String appkeyidd = (String) node.get("APPKEYID");
				String title = appModels.get(appkeyidd) == null ? "" : appModels.get(appkeyidd).getName();
				node.put("APPTITLE", title);
			}
			searchRecordServiceImpl.record(projectid, word, result, getCurrentUser(session));
			try {
				if (WucService.isEventAble()) {
					// 记录检索事件
					WucEventRecorder reorder = WucService.getRecorder();
					WucEventUsers users = new WucEventUsers();
					users.addUser(WucEventRole.OPRETOR.getKey(), WucService.getWucUser(getCurrentUser(session)),
							getCurrentIp(request));
					WucEventInfo info = new WucEventInfo(WucEventModle.WSCH_SEARCH.getKey(), word);
					info.addNum1(result.getSearchTime(), "检索时间");
					info.addNum2(result.getTotalSize(), "结果数量");
					reorder.runEvent(WucService.getWucSysid(), WucEventModle.WSCH_SEARCH.getKey(),
							WucEventModle.WSCH_SEARCH.getTitle(), info, users, true);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}

			Project project = projectServiceImpl.getProjectEntity(projectid);

			if (StringUtils.isNotBlank(project.getMinimgid())) {
				view.putAttr("minlogourl", fileBaseServiceImpl.getDownloadUrl(project.getMinimgid(), FileModel.IMG));
			}
			if (StringUtils.isNotBlank(project.getMaximgid())) {
				view.putAttr("maxlogourl", fileBaseServiceImpl.getDownloadUrl(project.getMaximgid(), FileModel.IMG));
			}

			return view.putAttr("result", result).putAttr("sortkey", sortkey).putAttr("sorttype", sorttype)
					.putAttr("sorttitle", sorttitle).putAttr("isSmart", isSmart).putAttr("dicunits", dicunits)
					.putAttr("dicrule", dicrule).putAttr("page", page).putAttr("word", word)
					.putAttr("fieldkeyid", fieldkeyid).putAttr("appkeyid", appkeyid)
					.returnModelAndView("web-simple/search/result");
		} catch (Exception e) {
			return view.setError(e.getMessage(), e).returnModelAndView("web-simple/simple-500");
		}
	}

	/**
	 * 构造字典树，带分布数量
	 * 
	 * @param dics
	 * @param projectid
	 * @return
	 */
	private List<Dictype> initStatDics(List<ResultDicNum> dics, String projectid) {
		List<Dictype> basetype = new ArrayList<Dictype>();
		{// 构造分布统计树
			Map<String, Long> numdic = new HashMap<>();
			for (ResultDicNum dic : dics) {
				numdic.put(dic.getId(), dic.getNum());
			}
			List<Dictype> alltype = dicTypeServiceImpl.getDictypes(projectid);
			for (Dictype type : alltype) {
				if (type.getParentid().equals("NONE") && StringUtils.isNotBlank(type.getFieldkey())) {
					List<Dictype> typeunit = new ArrayList<Dictype>();
					for (Dictype type2 : alltype) {
						if (type.getId().equals(type2.getSuperid())) {
							// -------------------------
							if (numdic.get(type2.getId()) != null) {
								type2.setNum(numdic.get(type2.getId()));
							}
							typeunit.add(type2);
						}
					}
					List<Map<String, Object>> treedata = BootstrapTreeViews.initData(typeunit, true,
							type.getSumable().equals("1"), type.getAbletype().equals("1"));
					if (BootstrapTreeViews.isHasNum(treedata)) {
						// 匹配到查询结果的字典
						type.setTreeData(treedata);
						type.setTreeDataJson(JSON.toJSONString(type.getTreeData()));
						basetype.add(type);
					}
				}
			}
		}
		return basetype;
	}

	/**
	 * 执行查询
	 * 
	 * @param projectid
	 * @param appkeyid
	 * @param fieldkeyid
	 * @param word
	 * @param page
	 * @return
	 * @throws IOException
	 * @throws ParseException
	 */
	private IndexResult runDoSearch(String projectid, String appkeyid, String fieldkeyid, String word, Integer page,
			String dicrule, String resultid, String sortkey, String sorttype, List<ResultDicNum> dics,
			Set<String> popkeys, boolean isSmart) throws IOException, ParseException {
		WschSearchServerInter searchServer = projectServiceImpl.getWschSearchServer(projectid);
		// 检索字段
		List<String> sfields = fieldServiceImpl.formatSearchField(projectid, fieldkeyid);
		if (word != null) {
			// 清理检索词
			word = word.replace("/", "");
		}

		if (isSmart) {
			// 精确 且 查询
			String[] arr = word.split("\\s+");
			for (String wordcase : arr) {
				searchServer.addRule(wordcase, sfields, fieldServiceImpl.getProjectFieldBoost(projectid, sfields),
						isSmart);
			}
		} else {
			// 非精确 或 查询
			searchServer.addRule(word, sfields, fieldServiceImpl.getProjectFieldBoost(projectid, sfields), isSmart);
		}

		if (appkeyid != null && !appkeyid.trim().equals("ALL") && !appkeyid.trim().equals("RESULT")) {
			// 检索范围域字段
			searchServer.addRule(appkeyid, "APPKEYID", false, true);
		}
		if (appkeyid.trim().equals("RESULT")) {
			// 结果中查询
			searchServer.setFilterResultId(resultid);
		}
		// 添加字典参数
		searchServer.addRule(dicTypeServiceImpl.getSearchRule(dicrule));
		// 添加排序条件
		searchServer.setSort(sortkey, sorttype);
		// 统计字典点匹配参数
		searchServer.setResultDicNums(dics);
		searchServer.setSearchPopKeys(popkeys);
		IndexResult result = searchServer.search(page, 10);
		virtualFieldServiceImpl.initVirtualField(result, projectid);
		result.initPages();
		Map<String, Field> fieldDics = fieldServiceImpl.getProjectFields(projectid);
		for (RuleInfo info : result.getRuleinfos()) {
			// 翻译检索信息中的域字段名称
			Field field = fieldDics.get(info.getFieldKey());
			if (field != null) {
				info.setFieldTitle(field.getName());
			}
		}
		return result;
	}

	/**
	 * 初始化页面参数
	 * 
	 * @param view
	 * @param projectid
	 */
	private void initSearchPageParas(ViewMode view, String projectid) {
		// 获得所有项目
		Project cproject = null;
		List<Project> projects = projectServiceImpl.getProjects();
		for (Project project : projects) {
			if (project.getId().equals(projectid)) {
				cproject = project;
			}
		}
		if (cproject == null) {
			throw new RuntimeException("未找到当前项目(" + projectid + ")");
		}
		// 获得项目业务
		List<Appmodel> appmodels = appModelServiceImpl.getAppmodels(projectid);
		// 获得项目检索域
		List<Field> fields = fieldServiceImpl.getSearchField(projectid);
		// 获得项目排序域
		List<Field> sorts = fieldServiceImpl.getSortField(projectid);

		List<String> hotwords = searchRecordServiceImpl.getHotWord(projectid, cproject.getKeyid(), 5);

		view.putAttr("projects", projects).putAttr("hotwords", hotwords).putAttr("fields", fields)
				.putAttr("projectid", projectid).putAttr("sorts", sorts).putAttr("cproject", cproject)
				.putAttr("appmodels", appmodels);
	}
}
